package cn.quevo.ucenter.server.service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.quevo.core.exception.CustomException;
import cn.quevo.core.lang.StringUtils;
import cn.quevo.core.util.BeanUtils;
import cn.quevo.ucenter.core.enums.OauthResultStatusEnum;
import cn.quevo.ucenter.core.token.OAuthIssuer;
import cn.quevo.ucenter.core.token.impl.OAuthIssuerImpl;
import cn.quevo.ucenter.server.dao.AccessTokenDao;
import cn.quevo.ucenter.server.entity.AccessToken;
import cn.quevo.ucenter.server.entity.OauthCode;
import cn.quevo.ucenter.server.entity.query.AccessTokenQuery;
import cn.quevo.ucenter.server.service.AccessTokenService;
import cn.quevo.ucenter.server.service.OauthCodeService;

/**
 * TokenService接口
 * 
 * @author July july_sky@foxmail.com
 * @date 2018年3月26日 下午5:22:49
 * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
 * @version 1.0
 */
@Service("accessTokenService")
@Transactional(transactionManager = "transactionManager", rollbackFor = { Exception.class })
public class AccessTokenServiceImpl implements AccessTokenService {
    @Resource(name = "accessTokenDao")
    private AccessTokenDao accessTokenDao;
    @Resource(name = "oauthCodeService")
    private OauthCodeService oauthCodeService;
//    private final static Logger log = LoggerFactory.getLogger(AccessTokenServiceImpl.class);

    @Override
    public Integer createAccessToken(AccessToken accessToken) throws CustomException {
        // 生成Access Token
        OAuthIssuer oAuthIssuer = new OAuthIssuerImpl();
        accessToken.setAccessToken(oAuthIssuer.accessToken());
        accessToken.setRefreshToken(oAuthIssuer.refreshToken());
        this.accessTokenDao.deleteHistory(accessToken);
        if (this.accessTokenDao.create(accessToken) <= 0) {
            throw new CustomException(OauthResultStatusEnum.INVALIDRENEW_TOKEN);
        }
        if (!StringUtils.isBlank(accessToken.getAuthCode())) {
            OauthCode oauthCode = new OauthCode();
            oauthCode.setAuthCode(accessToken.getAuthCode());
            oauthCode.setClientId(accessToken.getClientId());
            this.oauthCodeService.deleteOauthCode(oauthCode);
        }
        this.copy(accessToken);
        return 1;
    }

    @Override
    public AccessToken getAccessToken(AccessTokenQuery accessTokenQuery) throws CustomException {
        return this.accessTokenDao.getSinge(accessTokenQuery);
    }

    @Override
    public Integer updateRefreshToken(AccessToken accessToken) throws CustomException {
        AccessTokenQuery accessTokenQuery = new AccessTokenQuery();
        accessTokenQuery.setClientId(accessToken.getClientId());
        accessTokenQuery.setRefreshToken(accessToken.getRefreshToken());
        AccessToken at = this.getAccessToken(accessTokenQuery);
        if (at == null) {
            throw new CustomException(OauthResultStatusEnum.INVALID_REFRESH_TOKEN);
        }
        if (at.getAccessToken() == null || at.getExpireIn()) {
            accessToken.setAccessToken(new OAuthIssuerImpl().accessToken());
            if (this.accessTokenDao.createAccessTokenByRefresh(accessToken) <= 0) {
                throw new CustomException(OauthResultStatusEnum.INVALIDRENEW_TOKEN);
            }
            this.copy(accessToken);
            return 1;
        }
        accessToken.setVerNum(at.getVerNum());
        if (this.accessTokenDao.updateRefreshToken(accessToken) <= 0) {
            throw new CustomException(OauthResultStatusEnum.INVALIDRENEW_TOKEN);
        }
        this.copy(accessToken);
        return 1;
    }

    private void copy(AccessToken accessToken) throws CustomException {
        AccessTokenQuery accessTokenQuery = new AccessTokenQuery();
        accessTokenQuery.setClientId(accessToken.getClientId());
        accessTokenQuery.setAccessToken(accessToken.getAccessToken());
        accessTokenQuery.setRefreshToken(accessToken.getRefreshToken());
        BeanUtils.copyPropertiesExcludeNull(this.getAccessToken(accessTokenQuery), accessToken);
    }
}
